#include <assert.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>

#include "aceMesh_runtime_c.h"
#include "args.h"
#include "task.h"
#include "swlu.h"

#define THREAD_NUM 1

extern void slave_func_core(targs *args);

unsigned long rpcc()
{
    unsigned long time;
    asm("rtc %0" : "=r"(time) :);
    return time;
}

// composite task can only run on master
void level_1_core(targs *args)
{
    printf("start level_1_core\n");
    sleep(10);
    
    acemesh_begin_split_task("inner task");
    acemesh_task_generator((TASK_FUNCPTR)slave_func_core, NULL, 0);
    acemesh_end_split_task();
    acemesh_task_set_affinity(THREAD_NUM);
    printf("spawn and wait level_1_core\n");
    acemesh_spawn_and_wait(1);
    printf("end level_1_core\n");
}

void maketask(const int iter, const int thread_num)
{
    int itr;
    targs each;
    
    printf("start maketask\n");
    for (itr = 0; itr < iter; ++itr) {
        acemesh_begin_split_task("composite task");
        acemesh_composite_task_generator((TASK_FUNCPTR)level_1_core, &each, sizeof(targs));
        acemesh_task_set_type(4);
        acemesh_task_set_affinity(thread_num);
        acemesh_end_split_task();
    }
    printf("maketask itr end\n");
    acemesh_spawn_and_wait(1);
}

void makenormaltask(const int iter, const int thread_num) {
    int itr;
    targs each;
    
    printf("start maketask\n");
    for (itr = 0; itr < iter; ++itr) {
        acemesh_begin_split_task("composite task");
        acemesh_task_generator((TASK_FUNCPTR)slave_func_core, &each, sizeof(targs));
        acemesh_task_set_affinity(thread_num);
        acemesh_end_split_task();
    }
    printf("maketask itr end\n");
    acemesh_spawn_and_wait(1);
}


int main(int argc, char **argv)
{
    int iter, num_threads;
    int a;
    printf("wait for debug:");
    
    if (argc > 1) {
        iter = atoi(argv[1]);
    } else {
        iter = 1;
    }
    //swlu_debug_init();
    num_threads = THREAD_NUM;
    printf("main function\n");
    acemesh_runtime_init(num_threads);
    maketask(iter, num_threads);
    //makenormaltask(iter, num_threads);
    acemesh_runtime_shutdown();
    return 0;
}
